<template>
	<el-form
		ref="refMyForm"
		@submit.prevent
		@keyup.enter="query ? searchFn() : ''"
		:rules="defaultRules"
		:validate-on-rule-change="false"
		:disabled="detail"
		v-bind="$attrs"
		:class="[query ? 'myQueryForm' : 'validate--bottom']"
	>
		<slot v-bind="Object.assign({ query, detail, refMyForm }, $attrs)">
			<my-form-item v-bind="Object.assign({ formItem, query, detail, searchFn, refMyForm }, $attrs)">
				<!-- 插槽穿透 -->
				<template v-for="slotKey in Object.keys($slots)" :key="slotKey" v-slot:[slotKey]="obj">
					<slot :name="slotKey" v-bind="obj"></slot>
				</template>
			</my-form-item>
		</slot>
	</el-form>
</template>

<script setup name="MyForm">
const refMyForm = shallowRef(null);

/***
 * props
 * @property {Array} formItem 生成form表单的配置数组
 * @property {Boolean} query 是否默认添加查询 重置按钮
 * @property {Object} rules form表单的校验对象
 * @property {Boolean} [detail=false] 表单是否为详情展示表单默认为FALSE
 * @property {Function} [searchFn] 查询表单，查询函数
 */
const props = defineProps({
		formItem: {
			type: Array,
			default() {
				return [];
			}
		},
		query: {
			type: Boolean,
			default: false
		},
		rules: {
			type: Object,
			default: () => ({})
		},
		detail: {
			type: Boolean,
			default: false
		},
		searchFn: {
			type: Function
		}
	}),
	// 默认必填
	defaultRules = computed(() => {
		if (!props.query && !props.detail) {
			const rules = Object.create(null);
			props.formItem.forEach((item) => {
				if (item.required) {
					rules[item.prop] = {
						required: true,
						message: `${item.label}不能为空`,
						trigger: item.trigger
							? item.trigger
							: ['cascader', 'select', 'date', 'file', 'img'].includes(item.itemType)
								? 'change'
								: 'blur'
					};
				}
			});
			return Object.assign(rules, props.rules);
		} else {
			return {};
		}
	});

// 查询表单时，查询函数必需传递
watch(
	() => props.query,
	(val) => {
		if (val) {
			if (!props.searchFn) throw new Error('query is true，searchFn is required');
		}
	},
	{
		immediate: true
	}
);

// 暴露el-form自身方法
defineExpose({
	...new Proxy(
		{},
		{
			get(target, key) {
				return refMyForm.value?.[key];
			},
			has(target, key) {
				return key in refMyForm.value;
			}
		}
	)
});
</script>

<style lang="scss" scoped>
.myQueryForm {
	:deep() {
		.el-input__inner {
			width: 100%;
		}
		.query-form-item {
			margin-right: 0 !important;
		}
		.el-form-item__label {
			display: flex;
			justify-content: space-between;
		}
	}
}
:deep(.el-input),
:deep(.el-input__wrapper),
:deep(.el-textarea) {
	width: 100% !important;
	box-sizing: border-box;
}
</style>
